/*
 * @(#)PatientIdentifierTransformer.java
 * Date 2013-09-25
 * Version 1.0
 * Author Jim Horner
 * Copyright (c)2012
 */


package us.hornerscorners.lamppost.registry.transformer.model;

import javax.enterprise.context.ApplicationScoped;

import javax.inject.Inject;

import oasis.names.tc.ebxml_regrep.xsd.rim._3.ExternalIdentifierType;
import oasis.names.tc.ebxml_regrep.xsd.rim._3.SlotType1;

import org.apache.commons.lang3.StringUtils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import us.hornerscorners.lamppost.exception.ConversionException;
import us.hornerscorners.lamppost.exception.ServiceActionError;
import us.hornerscorners.lamppost.exception.SeverityType;

import us.hornerscorners.lamppost.model.common.InstanceIdentifier;

import us.hornerscorners.lamppost.registry.constant.ErrorCode;
import us.hornerscorners.lamppost.registry.constant.QuerySlotName;

import us.hornerscorners.lamppost.registry.utils.XDSUtils;

import us.hornerscorners.lamppost.transformer.AbstractTransformer;

import us.hornerscorners.lamppost.utils.OIDUtils;


/**
 * Class description
 *
 *
 * @version        v1.0, 2013-09-25
 * @author         Jim Horner
 */
@ApplicationScoped
public class PatientIdentifierTransformer
        extends AbstractTransformer<ExternalIdentifierType, InstanceIdentifier> {

    /** Field description */
    @Inject
    private LocalizedStringTransformer localizedStringTransformer;

    /** Field description */
    private final Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * Method description
     *
     *
     * @param eid
     *
     * @return
     *
     * @throws ConversionException
     */
    @Override
    public InstanceIdentifier transform(ExternalIdentifierType eid)
            throws ConversionException {

        InstanceIdentifier result = transform(XDSUtils.parseNameString(eid.getName()),
                                        eid.getValue());

        result.setEntryURN(XDSUtils.assignEntryUUID(eid.getId()));

        // versioning
        result.setEntryLogicalURN(StringUtils.defaultIfBlank(eid.getLid(),
                result.getEntryURN()));
        result.setEntryVersion(
            StringUtils.defaultIfBlank(
                XDSUtils.parseVersionName(eid.getVersionInfo()), "1"));

        result.getDisplayNames().addAll(
            this.localizedStringTransformer.transform(eid.getName()));
        result.getDescriptions().addAll(
            this.localizedStringTransformer.transform(eid.getDescription()));

        return result;
    }

    /**
     * Method description
     *
     *
     * @param slot
     *
     * @return
     *
     * @throws ConversionException
     */
    public InstanceIdentifier transform(SlotType1 slot) throws ConversionException {

        return transform(slot.getName(), XDSUtils.parseFirstValue(slot));
    }

    /**
     * Method description
     *
     *
     * @param slotName
     * @param idstr
     *
     * @return
     *
     * @throws ConversionException
     */
    public InstanceIdentifier transform(QuerySlotName slotName, String idstr)
            throws ConversionException {

        return transform(slotName.getCode(), idstr);
    }

    /**
     * Method description
     *
     *
     * @param idstr
     *
     * @return
     *
     * @throws ConversionException
     */
    private InstanceIdentifier transform(String slotName, String idstr)
            throws ConversionException {

        InstanceIdentifier result = null;
        String[] pieces = StringUtils.splitPreserveAllTokens(idstr, "^");

        if ((pieces != null) && (pieces.length == 4)) {

            String extension = pieces[0];
            String[] rootarr = StringUtils.splitPreserveAllTokens(pieces[3], "&");

            if ((rootarr != null) && (rootarr.length == 3)) {

                // TODO handle mapping other types (DNS, etc) to OID
                // see ITI-2x Appendix E
                // ITI-3 4.1.7, constrains CX to OID
                if (OIDUtils.isValid(rootarr[1])) {

                    result = new InstanceIdentifier();

                    result.setExtension(extension);
                    result.setRoot(rootarr[1]);
                    result.setAssigningAuthorityName(rootarr[0]);
                }
            }
        }

        if (result == null) {

            String msg = String.format("Slot [%s] value [%s] is not a valid CX value.",
                                       slotName, idstr);
            ServiceActionError error =
                new ServiceActionError(ErrorCode.XDSRegistryMetadataError.getCode(), msg,
                                       SeverityType.Error);

            throw new ConversionException(getClass(), error);
        }

        return result;
    }
}
